package golf.stockdata.connector.sms;

import golf.stockdata.connector.sms.dataobject.thaibulk.SMS_Type;
import golf.stockdata.framework.exception.AbilityInitializationException;
import golf.stockdata.framework.exception.ConnectorCallException;

import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Properties;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;

public class ThaiBulkSMSConnectorImpl implements SMSConnector {
	
	private String userName;
	private String password;
	private String force;
	private String url;
	
	private static final SimpleDateFormat SDF = new SimpleDateFormat("yyMMddHHmm");
	private static JAXBContext JAXB_CONTEXT ;
	
	static{
		try {
			JAXB_CONTEXT = JAXBContext.newInstance(SMS_Type.class);
		} catch (JAXBException e) {
			e.printStackTrace();
		}
	}

	public void initializeAbility(Properties props) {
		
		userName = props.getProperty("userName");
		if(userName == null){
			 throw new AbilityInitializationException("userName is missing");
		}
		
		password = props.getProperty("password");
		if(password == null){
			 throw new AbilityInitializationException("password is missing");
		}
		
		url = props.getProperty("url");
		if(url == null){
			 throw new AbilityInitializationException("url is missing");
		}
		
		String isPremium = props.getProperty("isPremium");
		if(isPremium == null){
			 throw new AbilityInitializationException("isPremium is missing");
		}else if(!isPremium.equalsIgnoreCase("y") && !isPremium.equalsIgnoreCase("n")){
			 throw new AbilityInitializationException("isPremium can only be Y or N");
		}
		if(isPremium.equalsIgnoreCase("y")){
			force = "premium";
		}else{
			force = "Standard";
		}
		
	}

	public void call(String phoneNumber, String message, String sender) throws ConnectorCallException {
		
		try{
			HttpClient httpclient = new DefaultHttpClient();
			HttpPost httppost = new HttpPost(url);

			List<NameValuePair> params = new ArrayList<NameValuePair>(2);
			params.add(new BasicNameValuePair("username", userName));
			params.add(new BasicNameValuePair("password", password));
			params.add(new BasicNameValuePair("msisdn", phoneNumber));
			params.add(new BasicNameValuePair("message", message));
			params.add(new BasicNameValuePair("sender", sender));
			params.add(new BasicNameValuePair("ScheduledDelivery", SDF.format(new Date(System.currentTimeMillis()))));
			params.add(new BasicNameValuePair("force", force));
			httppost.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));

			//Execute and get the response.
			HttpResponse response = httpclient.execute(httppost);
			HttpEntity entity = response.getEntity();

			if (entity != null) {
			    InputStream instream = entity.getContent();
			    try {
			    	SMS_Type smsResponseObj = createResponseObject(instream);
			    	if((smsResponseObj.getStatus() != null
			    			&& !smsResponseObj.getStatus().equals("1"))
			    		|| (smsResponseObj.getQueue() != null
			    			&& !smsResponseObj.getQueue().getStatus().equals("1"))){
			    		
			    		StringWriter strWrt = new StringWriter();
			    		Marshaller m = JAXB_CONTEXT.createMarshaller();
			    		m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
			    		m.marshal(smsResponseObj, strWrt);
			    		
			    		throw new ConnectorCallException("SMS Sending error:\n" + strWrt.toString());
			    	}
			    } catch (JAXBException e) {
					throw new ConnectorCallException(
							"JAXB error during mashalling the output:"
									+ e.getMessage());
					} finally {
			        instream.close();
			    }
			}
		}catch(IOException e){
			
		}
	}
	
	protected SMS_Type createResponseObject(InputStream xmlResponse) throws ConnectorCallException{
		
		try {
			
			Unmarshaller um = JAXB_CONTEXT.createUnmarshaller();
			SMS_Type smsOutput = (SMS_Type)um.unmarshal(xmlResponse);
			return smsOutput;
			
		} catch (JAXBException e) {
			throw new ConnectorCallException("JAXB error during unmashalling the output:" + e.getMessage());
		}
		
	}
	
}
